package com.app.brilliant.util;

import com.qiniu.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.*;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

public class PBEUtils {
    private static String ALGORITHM = "DES";//DES
    private static byte[] keyBytes="ndyxapp".getBytes();

    private static String ALGORITHM_PBE = "PBEWITHMD5andDES";
    private static String password="ndyxapp";
    static Key key;
    static byte[] salt;
    static {
        try{
            key=toKey();
            salt="ndyxSxjh".getBytes();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //文件加密
    public static void EncFile(File srcFile, File encFile) throws Exception {
        Long filelength = srcFile.length();  //文件长度
        byte[] filecontent = new byte[filelength.intValue()]; //文件内容
        if (!srcFile.exists()) {
            return;
        }
        if (!encFile.exists()) {
            encFile.createNewFile();
        }
        InputStream fis = new FileInputStream(srcFile);
        OutputStream fos = new FileOutputStream(encFile);

        fis.read(filecontent);

        fos.write(EncoderByPBE(filecontent,key, salt));

        fis.close();
        fos.flush();
        fos.close();
    }

    //文件解密
    public static void DecFile(File encFile, File decFile) throws Exception {

        Long filelength = encFile.length();  //文件长度
        byte[] filecontent = new byte[filelength.intValue()]; //文件内容

        if(!encFile.exists()){
            System.out.println("encrypt file not exixt");
            return;
        }
        if(!decFile.exists()){
            System.out.println("decrypt file created");
            decFile.createNewFile();
        }

        InputStream fis  = new FileInputStream(encFile);
        OutputStream fos = new FileOutputStream(decFile);

        fis.read(filecontent);

        fos.write(DecoderByPBE(filecontent,key, salt));

        fis.close();
        fos.flush();
        fos.close();
    }

    public static String EncString(String src) throws Exception {
        byte[] content = src.getBytes("utf-8");
        byte[] byPBE = EncoderByPBE(content, key, salt);
        return new String(byPBE,"utf-8");
    }

    public static byte[] EncToByte(String src) throws Exception {
        byte[] content = src.getBytes("utf-8");
        byte[] byPBE = EncoderByPBE(content, key, salt);
        return byPBE;
    }
    public static String decString(String src) throws Exception {
        byte[] content = src.getBytes("utf-8");
        byte[] byPBE = DecoderByPBE(content, key, salt);
        return new String(byPBE,"utf-8");
    }

    public static byte[] encodeByPBE(String src) throws Exception {
        byte[] content = src.getBytes("utf-8");
        byte[] byPBE = EncoderByPBE(content, key, salt);
        return byPBE;
    }

    public static byte[] decodeByPBE(byte[] content) throws Exception {
        byte[] byPBE = DecoderByPBE(content, key, salt);
        return byPBE;
    }
    //Base64加密算法
    public static byte[] EncoderByBase64(byte[] base64Byte) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        byte[] base64= Base64.encode(base64Byte, Base64.DEFAULT);
        return base64;
    }
    //Base64解密算法
    public static byte[] DecoderByBase64(byte[] base64Byte) throws NoSuchAlgorithmException, UnsupportedEncodingException{
        byte[] base64=Base64.decode(base64Byte, Base64.DEFAULT);//解密算法
        return base64;
    }

    //DES加密算法
    public static byte[] EncoderByDES(byte[] DESByte)
            throws Exception{
        DESKeySpec keySpec=new DESKeySpec(keyBytes);  //加密算法
        SecretKeyFactory keyFactory= SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey key=keyFactory.generateSecret(keySpec);   //产生密钥

        Cipher cipher=Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(keySpec.getKey()));
        byte[] result=cipher.doFinal(DESByte);
        return result;
    }
    //DES解密算法
    public static byte[] DecoderByDES(byte[] DESByte)
            throws Exception{
        DESKeySpec keySpec=new DESKeySpec(keyBytes);
        SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey key=keyFactory.generateSecret(keySpec);  //产生密钥

        Cipher cipher=Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(keyBytes));
        byte[] result=cipher.doFinal(DESByte);
        return result;
    }

    //PBE salt初始化
    public static byte[] initSalt() throws Exception {
        byte[] salt = new byte[8];
        Random random = new Random();
        random.nextBytes(salt);
        return salt;
    }

    //转换密钥
    private static Key toKey() throws Exception {
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM_PBE);
        SecretKey secretKey = keyFactory.generateSecret(keySpec);
        return secretKey;
    }

    //PBE加密算法
    public static byte[] EncoderByPBE(byte[] PBEByte,Key key, byte[] salt) throws Exception{
        PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
        Cipher cipher = Cipher.getInstance(ALGORITHM_PBE);
        cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
        return cipher.doFinal(PBEByte);
    }
    //PBE解密算法
    public static byte[] DecoderByPBE(byte[] PBEByte,Key key,byte[] salt) throws Exception{
        PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
        Cipher cipher = Cipher.getInstance(ALGORITHM_PBE);
        cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
        return cipher.doFinal(PBEByte);
    }


    //MD5加密算法
    public static byte[] EncoderByMd5(byte[] md5Byte) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        //确定计算方法
        MessageDigest md5=MessageDigest.getInstance("MD5");//加密算法
        md5.update(md5Byte);
        byte[] newByte = md5.digest();
        return newByte;
    }
}
